﻿using CacheAttribute.Attributes;
using CacheAttribute.Exceptions;
using CacheAttribute.Filter;
using CacheAttribute.Models;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Text;

namespace CacheAttribute.Utils
{
    /// <summary>
    /// 缓存选项
    /// 主要是提供自定义缓存策略的方法
    /// </summary>
    public class CacheOperation
    {
        private readonly ILogger<CacheOperation> logger;
        /// <summary>
        /// 无参构造函数中提供默认的实现方法
        /// </summary>
        public CacheOperation(ILogger<CacheOperation> logger)
        {
            this.logger = logger;

            //缓存初始化策略
            CacheInit_strategy = (context, _cache) => {

                try {
                    ControllerActionDescriptor controller = (ControllerActionDescriptor)context.ActionDescriptor;

                    MethodInfo action = controller.MethodInfo;

                    CacheInitAttribute attribute = (CacheInitAttribute)action.GetCustomAttribute(typeof(CacheInitAttribute));

                    string real_CacheName = CacheNameResolver.ResolveTotalName(attribute.Totoal_Name, context);

                    _cache.Set(attribute.preffix + real_CacheName, attribute.Init_Data);

                    return true;
                }
                catch (CacheStrategyException e)
                {
                    logger.LogError("策略执行错误---");
                    return false;
                }

            };

            //缓存删除行为策略
            CacheDel_strategy = (context, _cache) => {

                try
                {
                    ControllerActionDescriptor controller =  (ControllerActionDescriptor)context.ActionDescriptor;

                    MemberInfo action = controller.MethodInfo;

                    CacheDelAttribute attribute = (CacheDelAttribute)action.GetCustomAttribute(typeof(CacheDelAttribute));
                    //不生效则不去执行
                    if (attribute.work == false)
                        return false;

                    //如果传入的ExactCache不为空，则为删除单个确定名称的缓存，（需对参数进行解析来换取正确的缓存名）
                    string Exc = attribute.ExactCache;

                    //如果传入的Regex不为空，则为模式匹配的批量删除
                    string Reg = attribute.Regex;

                    if (!string.IsNullOrEmpty(Exc) && !string.IsNullOrEmpty(Reg)) throw new CacheDelArgsException("ERROR,CACHE_DELETE");

                    if (!string.IsNullOrEmpty(Exc))
                    {
                        string real_CacheName = CacheNameResolver.ResolveTotalName(attribute.ExactCache, context);
                        _cache.Remove(attribute.ExactCache);
                        return true;
                    }

                    if (!string.IsNullOrEmpty(Reg))
                    {
                        _cache.RemovePattern(Reg);
                        return true;
                    }
                    return true;


                } catch (CacheDelArgsException E)
                {
                    logger.LogError("缓存删除错误" + E.ToString());
                    return false;
                }
            };

            //[CacheAble策略]的方法执行前，第一个策略每一行都注释一下，如果回头看只需参考这个即可
            CacheAble_Strategy_Before = (context, _cache) => {
                //获取调用接口的Controller
                ControllerActionDescriptor controller = (ControllerActionDescriptor)context.ActionDescriptor;
                //进一步获取调用的接口的反射对象
                MethodInfo method = controller.MethodInfo;
                //从反射上拿到策略对应的Attribute,
                CacheAbleAttribute attribute = (CacheAbleAttribute)method.GetCustomAttribute(typeof(CacheAbleAttribute));

                //获取Attribute中需要解析的缓存名属性TotalName,解析ToTalName,替换得出真正的缓存名
                string real_cacheName = CacheNameResolver.ResolveTotalName(attribute.Totoal_Name, context);

                //如果注解的参数为空则直接报异常
                if (string.IsNullOrEmpty(attribute.preffix) || string.IsNullOrEmpty(attribute.Totoal_Name))
                    throw new CacheAbleArgsException("The Args Cannot Be NULL");

                //拿到解析的缓存名去缓存里找是否有该缓存
                if (_cache.Exist(attribute.preffix + real_cacheName)&&attribute.work==true)
                {

                    //StandResult<object> res = _cache.Get<StandResult<object>>(attribute.preffix + real_cacheName); 测试用的标志返回类型

                    //获取返回值的类型
                    Type returnType = method.ReturnType;
                    //获取泛型Get方法的反射（通过返回值的Type指定方法泛型）
                    MethodInfo GetGen = _cache.GetType().GetMethod("GetGen").MakeGenericMethod(returnType);
                    //放射调用泛型Get方法，获取正确的缓存信息
                    object res = GetGen.Invoke(_cache,new object[] {attribute.preffix+real_cacheName});

                    return res;
                }
                else
                {
                    return null; //没找到就返回Null
                }
                
            };

            //[CacheAble策略]方法执行后
            CacheAble_Strategy_After = (Executedcontext,Executingcontext, _cache) => {

                //获取调用方法的反射
                ControllerActionDescriptor controller = (ControllerActionDescriptor)Executedcontext.ActionDescriptor;
                //获取调用方法的反射
                MethodInfo method = controller.MethodInfo;

                CacheAbleAttribute attribute = (CacheAbleAttribute)method.GetCustomAttribute(typeof(CacheAbleAttribute));

                string real_CacheName = CacheNameResolver.ResolveTotalName(attribute.Totoal_Name, Executingcontext);

                if (string.IsNullOrEmpty(attribute.preffix) || string.IsNullOrEmpty(attribute.Totoal_Name))
                    throw new CacheAbleArgsException("The Args Cannot Be NULL");

                if (!_cache.Exist(attribute.preffix+real_CacheName)&&attribute.work==true)
                {
                    ObjectResult res = (ObjectResult)Executedcontext.Result;
                    _cache.Set(attribute.preffix + real_CacheName, res.Value);
                    logger.LogInformation("设置了缓存--------"+res.ToString());
                }


            };


            //[CahceUpdate策略]的方法执行前
            CacheUpdate_strategy_Before = (context, _cache) => {
                ControllerActionDescriptor controller = (ControllerActionDescriptor)context.ActionDescriptor;

                MethodInfo method = controller.MethodInfo;

                CacheAbleAttribute attribute = (CacheAbleAttribute)method.GetCustomAttribute(typeof(CacheAbleAttribute));

                //解析缓存名
                string real_CacheName = CacheNameResolver.ResolveTotalName(attribute.Totoal_Name, context);

                //如果注解的参数为空则直接报异常
                if (string.IsNullOrEmpty(attribute.preffix) || string.IsNullOrEmpty(attribute.Totoal_Name))
                    throw new CacheAbleArgsException("The Args Cannot Be NULL");

                if (_cache.Exist(attribute.preffix + real_CacheName) && attribute.work == true)
                {
                    //StandResult<object> res = _cache.Get<StandResult<object>>(attribute.preffix + real_CacheName);
                    
                    Type returnType = method.ReturnType;

                    MethodInfo GetGen = _cache.GetType().GetMethod("GetGen").MakeGenericMethod(returnType);

                    object res = GetGen.Invoke(_cache, new object[] { attribute.preffix + real_CacheName });

                    return res;
                }
                else
                {
                    return null;
                }

            };

            //[CahceUpdate策略]的方法执行后
            CacheUpdate_strategy_After = (Executedcontext, Executingcontext, _cache) => {
                //获取调用方法的反射
                ControllerActionDescriptor controller = (ControllerActionDescriptor)Executedcontext.ActionDescriptor;

                MethodInfo method = controller.MethodInfo;

                CacheAbleAttribute attribute = (CacheAbleAttribute)method.GetCustomAttribute(typeof(CacheAbleAttribute));

                //解析TotalName
                string real_cacheName = CacheNameResolver.ResolveTotalName(attribute.Totoal_Name, Executingcontext);

                if (string.IsNullOrEmpty(attribute.preffix) || string.IsNullOrEmpty(attribute.Totoal_Name))
                    throw new CacheAbleArgsException("The Args Cannot Be NULL");

                if (!_cache.Exist(attribute.preffix + real_cacheName) && attribute.work == true)
                {
                    ObjectResult res = (ObjectResult)Executedcontext.Result;

                    _cache.Remove(attribute.preffix + real_cacheName);

                    _cache.Set(attribute.preffix + attribute.Totoal_Name, res.Value);
                    logger.LogInformation("设置了缓存--------" + res.ToString());
                }


            };
        }

        
        



        /// <summary>
        /// 自定义缓存策略------------方法执行前
        /// </summary>
        public Func<ActionExecutingContext,ICacheable,Object> CacheAble_Strategy_Before { get; set; }

        /// <summary>
        /// 自定义缓存策略-------------方法执行后
        /// </summary>
        public Action<ActionExecutedContext,ActionExecutingContext,ICacheable> CacheAble_Strategy_After { get; set; }

        /// <summary>
        /// 自定义删除策略
        /// </summary>
        public Func<ActionExecutingContext, ICacheable, bool> CacheDel_strategy { get; set; }

        /// <summary>
        /// 自定义更新策略-------------方法执行前
        /// </summary>
        public Func<ActionExecutingContext, ICacheable,Object> CacheUpdate_strategy_Before { get; set; }

        /// <summary>
        /// 自定义更新策略-------------方法执行后
        /// </summary>
        public Action<ActionExecutedContext,ActionExecutingContext, ICacheable> CacheUpdate_strategy_After { get; set; }

        /// <summary>
        /// 自定义初始化缓存值
        /// </summary>
        public Func<ActionExecutingContext, ICacheable,bool> CacheInit_strategy { get; set; }



    }
}
